﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using System.Data;
using System.Text.RegularExpressions;
using System.IO;
using System.Reflection;
using System.Collections;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;

namespace Star.Tools.Json
{
    /// <summary>
    /// 
    /// </summary>
    public static class JsonHelper
    {
        #region 序列化
        /// <summary>
        /// 将对象转换为Json字符串
        /// </summary>
        public static string ToJson(this object obj)
        {
            return ToJson(obj,null);
        }
        /// <summary>
        /// 序列化JSON
        /// </summary>
        /// <param name="instance">实例</param>
        /// <param name="timeFormat">时间格式</param>
        /// <returns>JSON</returns>
        public static string ToJson(this object instance, string timeFormat = null)
        {
            #region # 验证参数

            if (instance == null)
            {
                return null;
            }
            #endregion

            try
            {
                JsonSerializerSettings settting = new JsonSerializerSettings
                {
                    ReferenceLoopHandling = ReferenceLoopHandling.Ignore
                };
                if (!string.IsNullOrWhiteSpace(timeFormat))
                {
                    settting.DateFormatString = timeFormat;
                }

                return JsonConvert.SerializeObject(instance, Formatting.None, settting);
            }
            catch (InvalidOperationException exception)
            {
                throw new InvalidOperationException($"无法将给定实例序列化为JSON，请检查类型后重试！", exception);
            }
        }
      
        /// <summary>
        /// 将对象转换为Json字符串
        /// </summary>
        /// <param name="target">目标对象</param>
        /// <param name="isConvertSingleQuotes">是否将双引号转成单引号</param>
        public static string ToJsonString(this object target, bool isConvertSingleQuotes = false)
        {
            if (target == null)
                return "{}";
            var result = JsonConvert.SerializeObject(target);
            if (isConvertSingleQuotes)
                result = result.Replace("\"", "'");
            return result;
        }
        /// <summary>
        /// 将对象转换为Json字符串，并且去除两侧括号
        /// </summary>
        /// <param name="target">目标对象</param>
        /// <param name="isConvertSingleQuotes">是否将双引号转成单引号</param>
        public static string ToJsonWithoutBrackets(object target, bool isConvertSingleQuotes = false)
        {
            var result = ToJsonString(target, isConvertSingleQuotes);
            if (result == "{}")
                return result;
            return result.TrimStart('{').TrimEnd('}');
        }


        #endregion

        #region JsonDateTimeFormat(Json时间格式化)
        /// <summary>
        ///  将对象序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="ignoreNull">是否忽略时间类型</param>
        /// <returns></returns>
        public static string ToJson(this object obj, bool ignoreNull = false)
        {
            if (obj == null) return null;

            return JsonConvert.SerializeObject(obj, Formatting.None, new JsonSerializerSettings
            {
                DateFormatString = "yyyy-MM-dd HH:mm:ss",
                NullValueHandling = ignoreNull ? NullValueHandling.Ignore : NullValueHandling.Include
            });
        }
        /// <summary>
        /// 将对象序列化 自定义时间类型
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="datetimeformats">时间格式</param>
        /// <returns></returns>
        public static string ToJsonDateTimeFormat(this object obj, string datetimeformats)
        {
            var timeConverter = new Newtonsoft.Json.Converters.IsoDateTimeConverter { DateTimeFormat = datetimeformats };
            return JsonConvert.SerializeObject(obj, timeConverter);
        }



       

        #endregion

        #region  将Json字符串转换为对象
        /// <summary>
        /// 将Json字符串转换为对象
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static object ToObject(this string json)
        {
            return JsonConvert.DeserializeObject(json);
        }

        /// <summary>
        /// 将Json字符串转换为对象
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <param name="type">实体类型</param>
        /// <returns></returns>
        public static object ToObject(string json, Type type)
        {
            return JsonConvert.DeserializeObject(json, type);
        }
        /// <summary>
        /// 将Json字符串转换为对象
        /// </summary>
        /// <typeparam name="T">实体类型</typeparam>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static T ToObject<T>(this string Json)
        {
            if (string.IsNullOrWhiteSpace(Json))
                return default(T);
            return JsonConvert.DeserializeObject<T>(Json);
        }

        /// <summary>
        /// JSON反序列化对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">JSON</param>
        /// <returns>实例</returns>
        public static T JsonToObject<T>(this string json)
        {
            #region # 验证参数

            if (string.IsNullOrWhiteSpace(json))
            {
                return default(T);
            }

            #endregion

            try
            {
                return JsonConvert.DeserializeObject<T>(json);
            }
            catch (InvalidOperationException exception)
            {
                throw new InvalidOperationException($"无法将给定JSON反序列化为类型\"{typeof(T).Name}\"，请检查类型后重试！", exception);
            }
        }
        #endregion

        #region 反序列化List
        /// <summary>
        /// JSON字符串转 List 实体对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="Json"></param>
        /// <returns></returns>
        public static List<T> JonsToList<T>(this string Json)
        {
            return JsonConvert.DeserializeObject<List<T>>(Json);
        }

        /// <summary>
        /// 解析JSON数组生成对象实体集合
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="json">json数组字符串(eg.[{"ID":"112","Name":"石子儿"}])</param>
        /// <returns>对象实体集合</returns>
        public static List<T> DeserializeJsonToList<T>(string json) where T : class
        {
            JsonSerializer serializer = new JsonSerializer();
            StringReader sr = new StringReader(json);
            object o = serializer.Deserialize(new JsonTextReader(sr), typeof(List<T>));
            List<T> list = o as List<T>;
            return list;
        }

        /// <summary>
        /// 反序列化JSON到给定的匿名对象.
        /// </summary>
        /// <typeparam name="T">匿名对象类型</typeparam>
        /// <param name="json">json字符串</param>
        /// <param name="anonymousTypeObject">匿名对象</param>
        /// <returns>匿名对象</returns>
        public static T DeserializeAnonymousType<T>(string json, T anonymousTypeObject)
        {
            T t = JsonConvert.DeserializeAnonymousType(json, anonymousTypeObject);
            return t;
        }
        #endregion

        #region JSON字符串转DataTable

        /// <summary>
        /// JSON字符串转DataTable
        /// </summary>
        /// <param name="strJson"></param>
        /// <returns></returns>
        public static DataTable JsonToDataTable(this string strJson)
        {
            #region
            DataTable tb = null;
            //获取数据  
            Regex rg = new Regex(@"(?<={)[^}]+(?=})");
            MatchCollection mc = rg.Matches(strJson);
            for (int i = 0; i < mc.Count; i++)
            {
                string strRow = mc[i].Value;
                string[] strRows = strRow.Split(',');
                //创建表  
                if (tb == null)
                {
                    tb = new DataTable();
                    tb.TableName = "Table";
                    foreach (string str in strRows)
                    {
                        DataColumn dc = new DataColumn();
                        string[] strCell = str.Split(':');
                        dc.DataType = typeof(String);
                        dc.ColumnName = strCell[0].ToString().Replace("\"", "").Trim();
                        tb.Columns.Add(dc);
                    }
                    tb.AcceptChanges();
                }
                //增加内容  
                DataRow dr = tb.NewRow();
                for (int r = 0; r < strRows.Length; r++)
                {
                    //刘鹏：20160526修改
                    // object strText = strRows[r].Split(':')[1].Trim().Replace("，", ",").Replace("：", ":").Replace("/", "").Replace("\"", "").Trim();
                    object strText = "";
                    strText = Regex.Split(strRows[r], ":\"", RegexOptions.IgnoreCase)[1].Trim().Replace("，", ",").Replace("：", ":").Replace("/", "").Replace("\"", "").Trim();

                    if (strText.ToString().Length >= 5)
                    {
                        if (strText.ToString().Substring(0, 5) == "Date(")//判断是否JSON日期格式
                        {
                            strText = JsonToDateTime(strText.ToString()).ToString("yyyy-MM-dd HH:mm:ss");
                        }
                    }
                    dr[r] = strText;
                }
                tb.Rows.Add(dr);
                tb.AcceptChanges();
            }
            return tb;
            #endregion
        }
        /// <summary>
        /// JSON字符串转DateTime
        /// </summary>
        /// <param name="jsonDate"></param>
        /// <returns></returns>
        public static DateTime JsonToDateTime(string jsonDate)
        {
            string value = jsonDate.Substring(5, jsonDate.Length - 6) + "+0800";
            DateTimeKind kind = DateTimeKind.Utc;
            int index = value.IndexOf('+', 1);
            if (index == -1)
                index = value.IndexOf('-', 1);
            if (index != -1)
            {
                kind = DateTimeKind.Local;
                value = value.Substring(0, index);
            }
            long javaScriptTicks = long.Parse(value, System.Globalization.NumberStyles.Integer, System.Globalization.CultureInfo.InvariantCulture);
            long InitialJavaScriptDateTicks = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).Ticks;
            DateTime utcDateTime = new DateTime((javaScriptTicks * 10000) + InitialJavaScriptDateTicks, DateTimeKind.Utc);
            DateTime dateTime;
            switch (kind)
            {
                case DateTimeKind.Unspecified:
                    dateTime = DateTime.SpecifyKind(utcDateTime.ToLocalTime(), DateTimeKind.Unspecified);
                    break;
                case DateTimeKind.Local:
                    dateTime = utcDateTime.ToLocalTime();
                    break;
                default:
                    dateTime = utcDateTime;
                    break;
            }
            return dateTime;
        }

        #endregion


        public static string SerializeObjectLoop(object o)
        {
            string json = JsonConvert.SerializeObject(o, Formatting.None,
              new JsonSerializerSettings()
              {
                  ReferenceLoopHandling = ReferenceLoopHandling.Ignore
              });
            return json;

        }



        #region ToJson(将对象转换为Json字符串)

        /// <summary>
        /// 将对象转换为Json字符串
        /// </summary>
        /// <param name="target">目标对象</param>
        /// <param name="isConvertToSingleQuotes">是否将双引号转换成单引号</param>
        /// <param name="camelCase">是否驼峰式命名</param>
        /// <param name="indented">是否缩进</param>
        /// <returns></returns>
        public static string ToJson(object target, bool isConvertToSingleQuotes = false, bool camelCase = false,
            bool indented = false)
        {
            if (target == null)
            {
                return string.Empty;
            }

            var options = new JsonSerializerSettings();
            if (camelCase)
            {
                options.ContractResolver = new CamelCasePropertyNamesContractResolver();
            }

            if (indented)
            {
                options.Formatting = Formatting.Indented;
            }

            var result = JsonConvert.SerializeObject(target, options);
            if (isConvertToSingleQuotes)
            {
                result = result.Replace("\"", "'");
            }

            return result;
        }

        #endregion
        #region SerializableToFile(将对象序列化到Json文件)

        /// <summary>
        /// 将对象序列化到Json文件
        /// </summary>
        /// <param name="fileName">文件名，绝对路径</param>
        /// <param name="obj">对象</param>
        public static void SerializableToFile(string fileName, object obj)
        {
            lock (obj)
            {
                using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
                {
                    using (StreamWriter sw = new StreamWriter(fs, Encoding.UTF8))
                    {
                        sw.Write(ToJson(obj, false, false, true));
                    }
                }
            }
        }

        #endregion

        #region DeserializeFromFile(从Json文件反序列成对象)

        /// <summary>
        /// 从Json文件反序列成对象
        /// </summary>
        /// <typeparam name="T">对象类型</typeparam>
        /// <param name="fileName">文件名，绝对路径</param>
        /// <returns></returns>
        public static T DeserializeFromFile<T>(string fileName)
        {
            try
            {
                using (FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate))
                {
                    using (StreamReader sr = new StreamReader(fs, Encoding.UTF8))
                    {
                        return ToObject<T>(sr.ReadToEnd());
                    }
                }
            }
            catch (Exception)
            {
                throw;
            }
        }

        #endregion

        #region ToJsonByForm(将Form表单转换成Json字符串)

        /// <summary>
        /// 将Form表单转换成Json字符串
        /// </summary>
        /// <param name="formStr">Form表单字符串</param>
        /// <returns></returns>
        public static string ToJsonByForm(string formStr)
        {
            Dictionary<string, string> dicData = new Dictionary<string, string>();
            var data = formStr.Split('&');
            for (int i = 0; i < data.Length; i++)
            {
                var dk = data[i].Split('=');
                StringBuilder sb = new StringBuilder(dk[1]);
                for (int j = 2; j <= dk.Length - 1; j++)
                {
                    sb.Append(dk[j]);
                }

                dicData.Add(dk[0], sb.ToString());
            }

            return dicData.ToJson();
        }

        #endregion

        #region ToJObject(将Json字符串转换为Linq对象)

        /// <summary>
        /// 将Json字符串转换为Linq对象
        /// </summary>
        /// <param name="json">Json字符串</param>
        /// <returns></returns>
        public static JObject ToJObject(string json)
        {
            if (string.IsNullOrWhiteSpace(json))
            {
                return JObject.Parse("{}");
            }

            return JObject.Parse(json.Replace("&nbsp;", ""));
        }

        #endregion

        #region IsJson(判断字符串是否为Json格式)

        /// <summary>
        /// 判断字符串是否为Json格式。为效率考虑，仅做了开始和结束字符的验证
        /// </summary>
        /// <param name="json">json字符串</param>
        public static bool IsJson(string json)
        {
            json = json.Trim();
            return json.StartsWith("{") && json.EndsWith("}") || json.StartsWith("[") && json.EndsWith("]");
        }

        #endregion

        /// <summary>
        /// 将对象序列化 Json时间格式化yyyy-MM-dd HH:mm:ss
        /// </summary>
        /// <param name="json">json</param>
        /// <returns></returns>
        public static string JsonDateTimeFormat(this string json)
        {
            if (string.IsNullOrWhiteSpace(json))
            {
                return json;
            }

            json = Regex.Replace(json, @"\\/Date\((\d+)\)\\/", match =>
            {
                DateTime dt = new DateTime(1970, 1, 1);
                dt = dt.AddMilliseconds(long.Parse(match.Groups[1].Value));
                return dt.ToString("yyyy-MM-dd HH:mm:ss");
            });
            return json;
        }


    }
}
